from typing import Annotated, List

from fastapi import APIRouter, Depends, HTTPException, status, Path
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select

from app.core import dependencies
from app.db import session
from app.db.models import user as user_model
from app.db.models.gallery import Gallery
from app.schemas import user as user_schema
from app.schemas import credit as credit_schema
from app.schemas import gallery as gallery_schema
from app.services import user as user_service
from app.services import credit as credit_service
from app.core import security # For password reset hash

# Define allowed categories (can be moved to config or fetched from DB)
ALLOWED_CATEGORIES = ["风景", "人物", "抽象", "其他"] # Duplicated from gallery router for validation

router = APIRouter(prefix="/admin", tags=["Admin"], dependencies=[Depends(dependencies.get_current_active_admin)])

# --- User Management --- 

@router.get("/users", response_model=List[user_schema.User])
async def admin_list_users(
    db: Annotated[AsyncSession, Depends(session.get_db)],
    skip: int = 0,
    limit: int = 100
):
    """List users (Admin only)."""
    result = await db.execute(select(user_model.User).offset(skip).limit(limit))
    users = result.scalars().all()
    return users

@router.get("/users/{user_id}", response_model=user_schema.User)
async def admin_get_user(
    user_id: Annotated[int, Path(description="The ID of the user to get")],
    db: Annotated[AsyncSession, Depends(session.get_db)]
):
    """Get specific user details by ID (Admin only)."""
    user = await user_service.get_user(db, user_id=user_id)
    if not user:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
    return user

@router.put("/users/{user_id}", response_model=user_schema.User)
async def admin_update_user(
    user_id: Annotated[int, Path(description="The ID of the user to update")],
    user_in: user_schema.UserUpdate, # Schema allowing optional updates
    current_admin: Annotated[user_model.User, Depends(dependencies.get_current_active_admin)], # Get admin performing action
    db: Annotated[AsyncSession, Depends(session.get_db)]
):
    """Update user details (Admin only). Allows updating email, active status, admin status, and password."""
    user_db = await user_service.get_user(db, user_id=user_id)
    if not user_db:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")

    update_data = user_in.model_dump(exclude_unset=True) # Get only provided fields

    if "password" in update_data and update_data["password"]:
        # Hash the new password if provided
        hashed_password = security.get_password_hash(update_data["password"])
        update_data["password_hash"] = hashed_password
        del update_data["password"] # Remove plain password field
    elif "password" in update_data: # Handle case where password is explicitly set to None or empty
         del update_data["password"]

    if "email" in update_data:
        # Check if new email is already taken by another user
        existing_email_user = await user_service.get_user_by_email(db, update_data["email"])
        if existing_email_user and existing_email_user.id != user_id:
             raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Email already registered by another user."
            )
        user_db.email = update_data["email"]
    
    # Update other fields directly
    if "is_active" in update_data:
        user_db.is_active = update_data["is_active"]
    if "is_admin" in update_data:
        # Prevent admin from accidentally removing their own admin status via this endpoint?
        # if user_db.id == current_admin.id and not update_data["is_admin"]:
        #     raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Cannot remove own admin status")
        user_db.is_admin = update_data["is_admin"]
    if "password_hash" in update_data:
         user_db.password_hash = update_data["password_hash"]

    db.add(user_db)
    await db.commit()
    await db.refresh(user_db)
    return user_db

@router.delete("/users/{user_id}", status_code=status.HTTP_204_NO_CONTENT)
async def admin_delete_user(
    user_id: Annotated[int, Path(description="The ID of the user to delete")],
    current_admin: Annotated[user_model.User, Depends(dependencies.get_current_active_admin)],
    db: Annotated[AsyncSession, Depends(session.get_db)]
):
    """Delete a user (Admin only). Performs a hard delete."""
    if user_id == current_admin.id:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Cannot delete own admin account")

    user = await user_service.get_user(db, user_id=user_id)
    if not user:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")

    # Consider implications: related data (credits, history) might need cleanup or handling
    # SQLAlchemy cascades might handle some, but depends on setup.
    # For now, proceed with user deletion.
    await db.delete(user)
    await db.commit()
    return None

# --- Credit Management --- 

@router.put("/credits/{user_id}", response_model=credit_schema.Credit)
async def admin_set_user_credits(
    user_id: Annotated[int, Path(description="The ID of the user whose credits to set")],
    credit_update: credit_schema.CreditUpdate, # Schema with just the balance field
    current_admin: Annotated[user_model.User, Depends(dependencies.get_current_active_admin)],
    db: Annotated[AsyncSession, Depends(session.get_db)]
):
    """Set a specific user's credit balance (Admin only)."""
    # Verify user exists first
    user = await user_service.get_user(db, user_id=user_id)
    if not user:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")

    updated_credits = await credit_service.admin_set_credits(
        db=db,
        user_id=user_id,
        new_balance=credit_update.balance,
        admin_user_id=current_admin.id
    )
    return updated_credits

# --- Gallery Management --- 

@router.post("/gallery", response_model=gallery_schema.GalleryItem, status_code=status.HTTP_201_CREATED)
async def admin_upload_gallery_item(
    item_in: gallery_schema.GalleryItemCreate,
    current_admin: Annotated[user_model.User, Depends(dependencies.get_current_active_admin)],
    db: Annotated[AsyncSession, Depends(session.get_db)]
):
    """Upload a new item to the gallery (Admin only)."""
    # Validate category if using predefined list
    if item_in.category not in ALLOWED_CATEGORIES: # Use local list
         raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Invalid category. Allowed categories are: {ALLOWED_CATEGORIES}" # Use local list
        )

    db_item = Gallery(
        **item_in.model_dump(),
        uploaded_by=current_admin.id
    )
    db.add(db_item)
    await db.commit()
    await db.refresh(db_item)
    return db_item

@router.delete("/gallery/{item_id}", status_code=status.HTTP_204_NO_CONTENT)
async def admin_delete_gallery_item(
    item_id: Annotated[int, Path(description="The ID of the gallery item to delete")],
    db: Annotated[AsyncSession, Depends(session.get_db)] # Admin already verified by dependency
):
    """Delete an item from the gallery (Admin only)."""
    result = await db.execute(select(Gallery).filter(Gallery.id == item_id))
    item = result.scalars().first()
    if not item:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Gallery item not found")
    
    await db.delete(item)
    await db.commit()
    return None
